/* 
 *  IsoEngine V 1.0
 *  by Massimo Bernardi alemassimo@yahoo.it
 *  codes published under license GNU GPL v3 
 */
//<reference path="utility/ListItems.js" />

var Cos_a = 0.8944;
var Sin_a = 0.4472;
var IsIExplorer=(navigator.appName.indexOf("Explorer")>=0);
var IsMozilla=(navigator.appName.indexOf("Netscape")>=0); 
var Directions = {"Nord":0,"Sud":1,"Est":2,"Ovest":3,"NordEst":4,"NordOvest":5,"SudEst":6,"SudOvest":7};


function Position(x,y,z)
{
    this._x = x;
    this._y = y;
    this._z = z;
    this.setX = function(x)
    {
        this._x = x;
    }
    this.setY = function(y)
    {
        this._y = y;
    }
    this.setZ = function(z)
    {
        this._z = z;
    }
    this.X = function()
    {
        return this._x; 
    }
    this.Y = function()
    {
        return this._y; 
    }
    this.Z = function()
    {
        return this._z; 
    }
}

function FTimer ()
{
    this._lastTick = (new Date()).getTime();
    this.Seconds = function()
    {
        var seconds = this._frameSpacing / 1000;
        if(isNaN(seconds)) {
            return 0;
        }
        return seconds;
        
    };
    this.tick = function()
    {
        var currentTick = (new Date()).getTime();
        this._frameSpacing = currentTick - this._lastTick;
        this._lastTick = currentTick;
    };
}
function Frame (name,width,height,column,row,duration)
{
    this.id = name;
    this.Width = width;
    this.Height = height;
    this.col = column;
    this.line = row;
    this.W = function()
    {
        return this.Width;
    }
    this.H = function()
    {
        return this.Height;
    }
    this.X = function()
    {
        return this.Width * this.col;
    }
    this.Y = function()
    {
        return this.Height * this.line;
    }
    this.DeltaT = duration;
    this.Duration = function()
    {
        return this.DeltaT;
    }
}
function Animation(anminationName,ImgObj)
{
    this.id = anminationName;
    this.img = ImgObj;
    this.loop = true;
    this._frames = new generic.list();
    this._currFrame = null;
    this._currFrameIndex = 0;
    this._currFrameDuration = 0;
    this._enabled = true;
    this.Name = function()
    {
        return this.id;
    }
    
    this.addFrame = function(spr)
    {
        
        this._frames.add(spr);
    }
    this.Frames = function(sprtsList)
    {
        this._frames = sprtsList;
    }
    this.Enabled = function(enabled)
    {
        this._enabled = enabled;
    }
    this.GetFrame = function(Name)
    {
        return this._frames.findByID(Name);
    }
    this.GetCurrFrame = function ()
    {
        if (this._currFrame == null)
        {
            this._currFrame = this._frames.items[this._currFrameIndex];
            this._currFrameDuration = this._frames.items[this._currFrameIndex].Duration(); 
        }
        return this._currFrame;
    }
    this.Animate = function(DeltaT)
    {
        if (this._enabled)
        {
           
            if (this._currFrame == null)
            {
                this._currFrame = this._frames.items[this._currFrameIndex];
                this._currFrameDuration = this._frames.items[this._currFrameIndex].Duration(); 
            }
            else
            {
                this._currFrameDuration -= DeltaT;
                if ( this._currFrameDuration < 0)
                {
                    this._currFrameIndex++;
            
                    if(this._currFrameIndex == this._frames.items.length) 
                    {
                        if(this.loop)
                            this._currFrameIndex = 0;
                        else
                            this._currFrameIndex--;
                    }
                    this._currFrame = this._frames.items[this._currFrameIndex];
                    this._currFrameDuration = this._frames.items[this._currFrameIndex].Duration();
            
                }
            }
        }
        else
        {
            if (this._currFrame == null)
            {
                this._currFrame = this._frames.items[this._currFrameIndex];
                this._currFrameDuration = this._frames.items[this._currFrameIndex].Duration(); 
            }
        }
    }
    
}

function IsoObj(ID)
{
    this._tmr = new FTimer();
    this.YbaseCenterOnFrame = 0;
    this.XbaseCenterOnFrame = 0;
    this._visible = true;
    this.id = ID;
    
    this.Velocity =0;
    if (typeof generic != 'undefined' && generic!= null )
    {
        this._animations = new generic.list();
        this._routePoints = new generic.list();
    }
    this._currentAnimation = null;
    this._CurrAbsPosition = new Position(0,0,0);
    this._currRoutePointIndex = 0;
    this.SetObjCenter = function(xC,yC)
    {
        this.XbaseCenterOnFrame = yC;
        this.YbaseCenterOnFrame = xC;
    }
    this.ZCalc = function()
    {
        return  this._CurrAbsPosition.X() + this._CurrAbsPosition.Y() + this._CurrAbsPosition.Z();
    }
    this.AddRoutePosition(pos)
    {
        if (this._routePoints != null)
            {
                this._routePoints.add(pos);
            }
    }
    this.AddAnimation = function(anim)
    {
        this._animations.add(anim);
    }
    this.GetPosition = function()
    {
        return this._CurrAbsPosition;
    }
    this.SetPosition = function(x,y,z)
    {
        this._CurrAbsPosition = new Position (x,y,z);
    }
    
    this.setCurrAnim = function(animName)
    {
        this._currentAnimation = this._animations.items[this._animations.findByID(animName)];
    }
    this.Animate = function()
    {
        this._tmr.tick();
       
        this._currentAnimation.Animate( this._tmr.Seconds());
        
    }
    this.GetCurrFrame = function()
    {
        if (this._currentAnimation != null)
            return this._currentAnimation.GetCurrFrame();
        
        return null;
    }
    this.IsVisible = function()
    {
        return this._visible;
    }
    this.SetVisible = function(vis)
    {
        this._visible = vis;
    }
    
    
    
}

function IsometriToScreenCalc(Pos)
{
    
    var x_screen = ( Pos.X() - Pos.Y() ) * Cos_a;
    var y_screen = (( Pos.X() + Pos.Y() ) * Sin_a) - Pos.Z();
    var ScreenPos = new Position(x_screen,y_screen,0);
    return ScreenPos;
}

function InvertItems(item1,item2)
{
    var temp = item1 ;
    item1 = item2 ;
    item2 = temp;
}
function IsoEngine(canvID) {
    var canvas = document.getElementById(canvID);
    var cntx = canvas.getContext('2d');
    var initialized = false;
    canvas.width = canvas.parentNode.clientWidth;
    canvas.height = canvas.parentNode.clientHeight;
    var TilesList = new generic.list();
    var ObjsList = new generic.list();
    var tileObjsList = new generic.list();
    var resetCursorImg = "";
    var origen_x=250;
    var origen_y=0;
    this.tile_w=100;
    this.tile_h=50;
    var traslX = 0;
    var traslY = 0;
   
    this.backgroundcolor = '#000000';
    
    this.Draw = function()
    {
        // erase canvas area
        cntx.fillStyle = this.backgroundcolor;
        cntx.fillRect(0, 0, canvas.width, canvas.height);
        //draw all tiles
        
        for ( i = 0; i<tileObjsList.items.length; i++)
        {
            tileObjsList.items[i].Animate();
            frame = tileObjsList.items[i].GetCurrFrame();
            CanvPos = CalcTilePosition(tileObjsList.items[i].TilePosition,this.tile_h,this.tile_w );
            this.DrawObj(frame,CanvPos.X()-(this.tile_w/2),CanvPos.Y()-(this.tile_h/2),tileObjsList.items[i]._currentAnimation.img);
        }
        // draw all objs
        for ( i = 0; i<ObjsList.items.length; i++)
        {
            ObjsList.items[i].Animate();
            frame = ObjsList.items[i].GetCurrFrame();
            CanvPos = IsometriToScreenCalc(ObjsList.items[i].GetPosition() );
            this.DrawObj(frame,CanvPos.X()-ObjsList.items[i].XbaseCenterOnFrame,CanvPos.Y()-ObjsList.items[i].YbaseCenterOnFrame,ObjsList.items[i]._currentAnimation.img);
        }
    }
    
    this.Initialize = function()
    {
        initialized = true;
        this.update()
    }
    this.update = function() {
   
        if (initialized)
        {
            this.Draw();
        }
        
   
     
    }
    
    // PosX e PosY sono posizioni (finali) relative al canvas
    this.DrawObj = function (frm, PosX, PosY, img) 
    {
        if ( img != null)
        {
            cntx.save();

            var x1 = PosX + traslX;
            var y1 = PosY + traslY ;
    
            cntx.translate(x1, y1);
            //cntx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
            cntx.drawImage(img, frm.X(), frm.Y(),frm.W(),frm.H(),0,0,frm.W(),frm.H());
            cntx.stroke();
            cntx.restore();
        }
    }
    this.AddTileObj = function(obj)
    {
        var index = tileObjsList.findByID(obj.id);
        if ( index == -1)
        {
            tileObjsList.add(obj);
        }
        else
        {
            tileObjsList.items[index] =  obj;
        }
        return index;
    }
    
    this.AddObj = function(obj)
    {
        var index = ObjsList.findByID(obj.id);
        if ( index == -1)
        {
            ObjsList.add(obj);
        }
        else
        {
            ObjsList.items[index] =  obj;
        }
        return index;
           
    }
    
    this.GetMouseCoordinate = function (evt)
    {
        var mouseX = evt.clientX - canvas.offsetLeft;
        var mouseY = evt.clientY - canvas.offsetTop;
        var coordinateDisplay = new Array(mouseX,mouseY);
        return coordinateDisplay;
    }
    this.GetObj = function(ObjId)
    {
        var index = ObjsList.findByID(ObjId);
        if ( index == -1)
        {
            return null;
        }
        return ObjsList.items[index];
    }
    this.SortObjs = function()
    {
        if(tileObjsList.items.lenght>1)
        {
            for ( i = 0; i<tileObjsList.items.length; i++)
            {
                if (tileObjsList.items[i].ZCalc > tileObjsList.items[i+1].ZCalc )
                {
                    InvertItems(tileObjsList.items[i],tileObjsList.items[i+1]);
                }
            }  
        }
        if(ObjsList.items.length>1 )
        {
            for ( i = 0; i<ObjsList.items.length; i++)
            {
                if (ObjsList.items[i].ZCalc > ObjsList.items[i+1].ZCalc )
                {
                    InvertItems(ObjsList.items[i],ObjsList.items[i+1]);
                }
            }
        }
    }
    
   
    
}

function UnitVectorBWTwoPoint(pos1,pos2)
{
    x1 = pos1.X();y1 = pos1.Y();z1 = pos1.Z();
    x2 = pos2.X();y2 = pos2.Y();z3 = pos2.Z();
    dx = (x2-x1);
    dy = (y2-y1);
    dz = (z2-z1);
    dist = TwoPointsDistance(pos1,pos2);
    return new Position( (dx/dist) , (dy/dist) , (dz/dist) );
}
function TwoPointsDistance(pos1,pos2)
{
    x1 = pos1.X();y1 = pos1.Y();z1 = pos1.Z();
    x2 = pos2.X();y2 = pos2.Y();z3 = pos2.Z();
    qxd = Math.pow((x2-x1), 2); 
    qyd = Math.pow((y2-y1), 2); 
    qzd = Math.pow((z2-z1), 2); 
    return Math.sqrt(qxd+qyd+qzd);
}
function CalcTilePosition (pos,tile_height,tile_width)
{
     x = (pos.X() * tile_width / 2) - (pos.Y() * tile_width / 2)
     y = (pos.Y() * tile_height / 2) + (pos.X() * tile_height / 2)
    return new Position(x,y,0);
}


function TileObj(TileID,TilePosX,TilePosY,Z)
{
    this.id = TileID;
    this.TilePosition = new Position(TilePosX,TilePosY,Z);
    this._animations = new generic.list();
}
// ereditarietà IsoObj -> TileObj
TileObj.prototype = new IsoObj();
TileObj.prototype.constructor = TileObj;